#include "io_thread_pool.h"
#include <thread>
#include <algorithm>
#include <functional>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>

IOThreadPool::IOThreadPool()
:next_io_service_(0)
{
    init();
}

IOThreadPool::~IOThreadPool()
{
}

void IOThreadPool::init()
{
    int cup_num = std::thread::hardware_concurrency();
    for (int i = 0; i < cup_num; ++i)
    {
	io_service_ptr io_service(new boost::asio::io_service);
	work_ptr work(new boost::asio::io_service::work(*io_service));

	io_services_.push_back(io_service);
	works_.push_back(work);
    }
}

void IOThreadPool::run()
{
    vector<std::shared_ptr<std::thread> > threads;
    for (std::size_t i = 0; i < works_.size(); ++i)
    {
	std::shared_ptr<std::thread> thread(new std::thread(
	    boost::bind(&boost::asio::io_service::run, io_services_[i])));
	threads.push_back(thread);
    }

	BOOST_FOREACH(std::shared_ptr<std::thread> ptr, threads)
	{
		ptr->join();
	}
}

void IOThreadPool::stop()
{
	BOOST_FOREACH(io_service_ptr ptr, io_services_)
	{
		ptr->stop();
	}
}

boost::asio::io_service& IOThreadPool::getIOService()
{
    boost::asio::io_service& service = *io_services_[next_io_service_];

    next_io_service_ = (++next_io_service_ % io_services_.size());

    return service;
}